#include <windows.h>
#include <stdio.h>

__declspec(dllexport) void sideload (void)
{
    char * translation_buffer = (char *)malloc(1024*1024);
    strcpy(translation_buffer, "no text(translation_buffer)");
    //never free translation_buffer

    //load mod files
    OFSTRUCT mod_file_buffer;
    HFILE mod_file = HFILE_ERROR;
    int mod_is_disabled = 1;
    
    if(mod_file == HFILE_ERROR){
        mod_file = OpenFile("mods\\cn_2487394275\\resources-dlc3\\translationstrings.ini", &mod_file_buffer, OF_READ);
        HFILE disable_file = OpenFile("mods\\cn_2487394275\\disable.it", &mod_file_buffer, OF_READ);
        mod_is_disabled = disable_file != HFILE_ERROR; 
        if(mod_is_disabled){
            CloseHandle(disable_file);
        }
    }
    if(mod_file == HFILE_ERROR){
        mod_file = OpenFile("mods\\cn\\resources-dlc3\\translationstrings.ini", &mod_file_buffer, OF_READ);
        HFILE disable_file = OpenFile("mods\\cn\\disable.it", &mod_file_buffer, OF_READ);
        mod_is_disabled = disable_file != HFILE_ERROR; 
        if(mod_is_disabled){
            CloseHandle(disable_file);
        }
    }
    if(mod_file == HFILE_ERROR){
        mod_file = OpenFile("mods\\2487394275\\resources-dlc3\\translationstrings.ini", &mod_file_buffer, OF_READ);
        HFILE disable_file = OpenFile("mods\\2487394275\\disable.it", &mod_file_buffer, OF_READ);
        mod_is_disabled = disable_file != HFILE_ERROR; 
        if(mod_is_disabled){
            CloseHandle(disable_file);
        }
    }
    if(mod_file == HFILE_ERROR){
        free(translation_buffer);
        translation_buffer = NULL;
        // we didn't found mod folder
        // MessageBoxA(0, "Can't load mod file.", "From max chinese hijack", MB_ICONINFORMATION);
    }else if(mod_is_disabled){
        free(translation_buffer);
        translation_buffer = NULL;
        //mod is disabled, it is not an error.
    }else{
        DWORD size;
        if(!ReadFile(mod_file, translation_buffer, 1024*1024, &size, NULL)){
            free(translation_buffer);
            translation_buffer = NULL;
            MessageBoxA(0, "Can't read mod file.", "From max chinese hijack", MB_ICONINFORMATION);
        }else{
            //success
        }
        CloseHandle(mod_file);
    }




    // HINSTANCE hExe = LoadLibrary("isaac-ng.exe.unpacked.exe");
    HINSTANCE hExe = LoadLibrary("isaac-ng.exe");
    // char buff[60];
    if(hExe == NULL){
        MessageBoxA(0, "Can't find game base, please don't modify game exe name.", "From max chinese hijack", MB_ICONINFORMATION);
        return;
    }

    unsigned char * patch = (unsigned char *)hExe + 0x2472D1;

    // sprintf(buff,"hExe:%p %x %x %x",patch,(int)patch[0],(int)patch[1], (int)patch[2]);
    // MessageBoxA(0, buff, "From max chinese hijack", MB_ICONINFORMATION);


    if(patch[0] != 0xE8 || patch[1] != 0x1A || patch[2] != 0x7B){
        MessageBoxA(0, "Can't find correct address", "From max chinese hijack", MB_ICONINFORMATION);
        return;
    }

    DWORD old_protect;
    if(!VirtualProtect(patch, 4, PAGE_READWRITE,&old_protect)){
        MessageBoxA(0, "change page protect failed!", "From max chinese hijack", MB_ICONINFORMATION);
        return;
    }
    patch[1] = 0x6A;
    patch[2] = 0x82;

    if(!VirtualProtect(patch,4,old_protect,&old_protect)){
        MessageBoxA(0, "change page protect failed!(2)", "From max chinese hijack", MB_ICONINFORMATION);
        return;
    }

    if(patch[1] != 0x6A || patch[2] != 0x82){
        MessageBoxA(0, "patch failed!", "From max chinese hijack", MB_ICONINFORMATION);
        return;
    }


    //change the argument from stack
    //MessageBoxA(0, "patched!", "From max chinese hijack", MB_ICONINFORMATION);
    if(translation_buffer){
        unsigned char * translation_patch = (unsigned char *)hExe + 0x466E09;
        if(translation_patch[0] != 0xE8){
            MessageBoxA(0, "can't find translationstring.ini load instruction!", "From max chinese hijack", MB_ICONINFORMATION);
            return;
        }
        //this is the real function, which takes the content of translationstrings.ini form [esp]
        int jmp_target = (int)&translation_patch[1] + *(int*)&translation_patch[1] + 5;

        //prepare a shellcode
        unsigned char * patch_mem = VirtualAlloc(NULL, 100, MEM_COMMIT, PAGE_READWRITE);
        if(!patch_mem){
            MessageBoxA(0, "allocate patch memory failed!", "From max chinese hijack", MB_ICONINFORMATION);
            return;
        }

        // sprintf(buff,"buffer is : %p",translation_buffer);
        // MessageBoxA(0, buff, "From max chinese hijack", MB_ICONINFORMATION);


        //mov DOWRD PTR [esp+4], 0xdeadbeef
        //0xC7, 0x44, 0x24, 0x04, 0xEF, 0xBE, 0xAD, 0xDE
        patch_mem[0] = 0xC7;
        patch_mem[1] = 0x44;
        patch_mem[2] = 0x24;
        patch_mem[3] = 0x04;
        void **string_ptr = (void **)&patch_mem[4];
        *string_ptr = translation_buffer;
        //jmp somewhere
        patch_mem[8] = 0xe9;
        int*jmp_source = (int*)&patch_mem[9];
        *jmp_source = jmp_target - ((int)jmp_source + 5);
        if(!VirtualProtect(patch_mem, 100, PAGE_EXECUTE_READ,&old_protect)){
            MessageBoxA(0, "change page protect failed!(patch memory)", "From max chinese hijack", MB_ICONINFORMATION);
            return;
        }

        // change the original program

        if(!VirtualProtect(translation_patch, 8, PAGE_READWRITE,&old_protect)){
            MessageBoxA(0, "change page protect failed!", "From max chinese hijack", MB_ICONINFORMATION);
            return;
        }

        *(int*)&translation_patch[1] = (int)patch_mem - ((int)translation_patch + 5);

        if(!VirtualProtect(translation_patch,8,old_protect,&old_protect)){
            MessageBoxA(0, "change page protect failed!(2)", "From max chinese hijack", MB_ICONINFORMATION);
            return;
        }
    }

}
